#include<iostream>
#include<typeinfo>
#include<algorithm>

class Any
{
private:
    class BaseData
    {
    public:
    //提供几个虚函数，交给子类继承，未来能够通过父类指针调用子类的重写的虚函数
        virtual const std::type_info& Type() = 0;  //获取数据类型
        virtual BaseData* Clone()const = 0;           //克隆出一份子类对象，但是返回其父类切片指针
        virtual ~BaseData(){}                    //析构函数必须是虚函数
    };

    template<class T>
    class Data :public BaseData// 保存数据的类
    {
    public:
        T*_pd;
    //保存数据的指针
    public:
        Data(const T& val):_pd(nullptr){_pd = new T(val);std::cout<<"构造:"<<*_pd<<"  addr:"<<(void*)_pd<<std::endl;}   //数据保存在 Any 中，new一段空间拷贝一个，因为传进来的可能是一个临时对象
        ~Data(){std::cout<<"析构:"<<*_pd<<"   addr:"<<(void*)_pd<<std::endl;delete _pd;}
        const std::type_info& Type() {if(!_pd) return typeid(void);
                                    return typeid(T);/*typeid(*_pd)*/}
        BaseData* Clone()const {return new Data<T>(*_pd);}  
    };
private:
    BaseData* _pbase; //在Any类中只需要保存一个父类指针就行了
public: 
//要提供的接口
    Any():_pbase(nullptr){}         //提供空构造
    ~Any(){delete _pbase;}
    template<class T>               //构造
    Any(const T& val):_pbase(new Data<T>(val)){}
    BaseData* Clone()const{return _pbase->Clone();}   //调用 Data 的 Clone 接口就行
    Any(const Any& a)               //拷贝构造
    {
        if(a.Type()==typeid(void)) _pbase=nullptr;   //注意在拷贝之前要判断被拷贝的对象是否为空对象
        else  _pbase = a.Clone();
    }
    Any& operator=(const Any&a)     //赋值重载
    {
        Any tmp(a);
        std::swap(_pbase,tmp._pbase);
        return *this;
    }
    template<class T>
    Any& operator=(const T&val)     //支持隐式类型转换
    {
        Any tmp(val);
        std::swap(_pbase,tmp._pbase);
        return *this;
    }
    const std::type_info& Type()const {return _pbase->Type();} //获取数据类型
    template<class T>
    T* GetData()
    {
        //首先判断返回类型是否和我们的数据类型一致
        assert(typeid(T)==Type());
        //走到这里说明我们的数据类型就是 T ，换句话说，父类指针指向的是一个 Data<T> ,那么我们就可以强转成子类指针获取公有成员了
        return dynamic_cast<Data<T>*>(_pbase)->_pd;
    }
};
